import { baseURL, timeout } from "../config.js";
import { Toast, popup, fitterItem } from "./util.js";

let isRefreshing = false; // 是否正在刷新的标记
let requests = []; //重试队列，每一项将是一个待执行的函数形式

let anewParams = {
  url: "/mini/sys/operate/refresh_token",
  method: "POST",
  data: {},
};

function fun(url, method, data, loading = true, headers) {
  if (uni.getStorageSync("refreshToken")) {
    anewParams.data = {
      refreshToken: uni.getStorageSync("refreshToken"),
    };
  }

  let promise = new Promise((resolve, reject) => {
    let header = {
      "content-type": "application/json", // 默认值
    };
    let token = uni.getStorageSync("X-MINI-TOKEN");
    if (token) {
      header["X-MINI-TOKEN"] = token;
    }
    if (loading) {
      uni.showLoading({
        title: "加载中...",
        mask: true,
      });
    }
    uni.request({
      url: baseURL + url,
      method,
      timeout: timeout,
      data,
      dataType: "json",
      header: headers || header,
      success(res) {
        if (loading) {
          uni.hideLoading();
        }
        let statusCode = res.statusCode;
        switch (statusCode) {
          case 200:
            let code = res.data.code;
            switch (code) {
              case 500:
                if (url != "/sys/logout") {
                  Toast(res.data.message);
                } else {
                  resolve(res.data);
                }
                break;
              case 1000:
                resolve(res.data);
                break;
              case 200:
                isRefreshing = false;
                resolve(res.data);
                break;
              case 400:
                resolve(res.data);
                break;
              case 1001:
                Toast(
                  res.data.message + "，请检查房屋是否正确或重新选择与户主关系"
                );
                break;
              default:
                Toast(res.data);
                break;
            }
            break;
          case 400:
            resolve(res.data);
            break;
          case 404:
            Toast("请联系服务人员，错误代码：404,资源无法找到");
            break;
          case 500:
            if (res.data.message.indexOf("重新登录") != -1) {
              if (token) {
                Toast("登录状态失效，请重新登录");
                uni.clearStorageSync();
                setTimeout(() => {
                  uni.redirectTo({
                    url: "/pages/beforeLogin/beforeLogin",
                  });
                }, 1500);
                reject(res);
              }
            } else {
              Toast("服务器内部错误，错误代码：500");
            }
            break;
          case 502:
            Toast("请联系服务人员，错误代码：502");
            break;
          case 401:
            //这里是重点：让这个Promise一直处于Pending状态（即不调用resolve）
            new Promise((resolve2) => {
              // 用函数形式将 resolve 存入，等待刷新后再执行
              requests.push((token) => {
                if (!data) {
                  data = {};
                }
                token = `${token}`;
                //这里resolve
                resolve(fun(url, method, data));
              });
            });

            if (!isRefreshing) {
              console.log("token过期");
              isRefreshing = true; //第一个请求后，后面请求都不进入执行请求
              //调用刷新token的接口
              return fun(anewParams.url, anewParams.method, anewParams.data)
                .then((data) => {
                  if (data.code == 200) {
                    wx.setStorageSync("X-MINI-TOKEN", data.result.token);
                    // token 刷新后将数组的方法重新执行
                    requests.forEach((cb) => cb(data.result.token));
                    requests = []; // 重新请求完清空
                    return;
                  }

                  wx.removeStorageSync("X-MINI-TOKEN");
                  uni.redirectTo({
                    url: "/pages/beforeLogin/beforeLogin",
                  });
                })
                .catch((err) => {
                  //获取token失败，删除旧token，跳到登录页
                  try {
                    wx.removeStorageSync("X-MINI-TOKEN");
                  } catch (error) {}
                  uni.redirectTo({
                    url: "/pages/beforeLogin/beforeLogin",
                  });
                  return Promise.reject(err);
                });
            }
            break;
          default:
            break;
        }
      },
      fail(res) {
        reject(res);
        if (loading) {
          uni.hideLoading();
        }
      },
    });
  });
  return promise;
}

export let getAction = (url, data, header) =>
  fun(url, "GET", fitterItem(data), true, header);
export let postAction = (url, data, header) =>
  fun(url, "POST", data, true, header);
export let putAction = (url, data, header) =>
  fun(url, "PUT", data, true, header);
export let deleteAction = (url, data, header) =>
  fun(url, "DELETE", data, true, header);
export let httpAction = (url, method, data, loading, header) =>
  fun(url, method, data, loading, header);
